package com.tenbent.product.base.template;

import com.tenbent.product.base.bo.BizObject;
import com.tenbent.product.base.bo.BizObject.WhereColumn;
import com.tenbent.product.base.exception.TenbentException;
import com.tenbent.product.base.mapper.SqlMapper;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * mybatis CRUD 模板(单表)
 *
 * @author Randy
 *         <p>
 *         Created by ThinkPad on 2017/7/25.
 */
public class CrudTemplate<T extends BizObject> {

	private static final Logger logger = LoggerFactory.getLogger(CrudTemplate.class);

	/**
	 * 生成添加记录SQL(ID 数据库提供 自增)
	 */
	public String insert(T obj) throws TenbentException {

		obj.caculationColumnList();
		StringBuffer sql = new StringBuffer();
		sql = sql.append("insert into " + obj.tablename() + "(" + obj.returnInsertColumnsName() + ")" + " values("
				+ obj.returnInsertColumnsDefine() + ")");
		logger.debug("insetSql--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 生成添加记录SQL(ID 系统提供)
	 */
	public String insertContainPk(T obj) throws TenbentException {

		obj.caculationColumnList();
		StringBuffer sql = new StringBuffer();
		sql = sql.append("insert into " + obj.tablename() + "(id," + obj.returnInsertColumnsName() + ")"
				+ " values(#{id}," + obj.returnInsertColumnsDefine() + ")");
		logger.debug("insetSql--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 生成修改记录SQL
	 */
	public String update(T obj) throws TenbentException {

		String idname = obj.id();
		obj.caculationColumnList();
		StringBuffer sql = new StringBuffer();
		sql = sql.append("update " + obj.tablename() + " set " + obj.returnUpdateSet() + " where " + idname + "=#{"
				+ idname + "}");
		logger.debug("update_Sql--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 生成删除记录SQL
	 */
	public String delete(T obj) throws TenbentException {

		String idname = obj.id();
		StringBuffer sql = new StringBuffer();
		sql = sql.append("delete from " + obj.tablename() + " where " + idname + "=#{" + idname + "}");
		logger.debug("deleteSql--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 生成逻辑删除记录SQL
	 */
	public String deleteLogic(T obj) throws TenbentException {

		String idname = obj.id();
		StringBuffer sql = new StringBuffer();
		sql = sql.append(
				"update " + obj.tablename() + " set del_flag = 1, modify_id = #{modifyId}, gmt_modified = now() where "
						+ idname + "=#{" + idname + "}");
		logger.debug("deleteSql--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 生成根据主键查询记录SQL
	 */
	public String getByKey(T obj) throws TenbentException, InstantiationException, IllegalAccessException {

		String idname = obj.id();
		StringBuffer sql = new StringBuffer();
		sql.append("select * from " + obj.tablename() + " where del_flag = 0 and " + idname + "=#{" + idname + "}");
		logger.debug("getByIdSql--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 生成查询所有记录SQL
	 */
	public String getAll(Class<? extends BizObject> clazz)
			throws TenbentException, InstantiationException, IllegalAccessException {

		BizObject obj = clazz.newInstance();
		StringBuffer sql = new StringBuffer();
		sql.append("select * from " + obj.tablename() + " where del_flag = 0  order by " + obj.id() + " asc");
		logger.debug("getAll--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 根据对象属性是否有值进行查询
	 */
	public String queryByObj(T obj) throws TenbentException, InstantiationException, IllegalAccessException {

		StringBuffer sql = new StringBuffer();
		sql.append("select * from " + obj.tablename() + " where del_flag = 0 ");
		List<WhereColumn> columnList = obj.returnWhereColumnsName();
		if (columnList != null && !columnList.isEmpty()) {
			for (int i = 0; i < columnList.size(); i++) {
				WhereColumn column = columnList.get(i);
				sql.append("and " + column.name + "=#{" + column.valueName + "} ");
			}
		}
		sql.append("order by " + obj.id() + " asc ");
		logger.debug("queryByObj--->" + sql.toString());
		return sql.toString();
	}

	/**
	 * 根据对象属性是否有值进行查询
	 */
	public String queryByMap(Map<String, Object> paramMap)
			throws TenbentException, InstantiationException, IllegalAccessException {

		StringBuffer sql = new StringBuffer();
		try {
			Map<String, Object> paramMap1 = new HashedMap();
			paramMap1.putAll(paramMap);
			BizObject obj = (BizObject) Class.forName((String) paramMap1.get(SqlMapper.TABLE_NAME)).newInstance();
			Field[] fields = obj.getClass().getDeclaredFields();
			Field[] supFields = obj.getClass().getSuperclass().getDeclaredFields();
			Field[] allFields = ArrayUtils.addAll(fields, supFields);
			sql.append("select * from " + obj.tablename() + " where del_flag = 0 ");
			paramMap1.remove(SqlMapper.TABLE_NAME);
			if (paramMap1.containsKey("_ORIGINAL_PARAMETER_OBJECT")) {
				paramMap1.remove("_ORIGINAL_PARAMETER_OBJECT");
			}
			if (paramMap1.containsKey("First_PageHelper")) {
				paramMap1.remove("First_PageHelper");
			}
			if (paramMap1.containsKey("Second_PageHelper")) {
				paramMap1.remove("Second_PageHelper");
			}
			Set<String> set = paramMap1.keySet();
			if (set != null && !set.isEmpty()) {
				Object[] columnNames = set.toArray();
				for (int i = 0; i < columnNames.length; i++) {
					Object name = columnNames[i];
					for (Field field : allFields) {
						String fieldName = field.getName();
						String annotionFieldName = obj.getAnnotationFieldName(field);
						if (StringUtils.equals(name.toString(), fieldName)
								|| StringUtils.equals(name.toString(), annotionFieldName)) {
							sql.append("and " + annotionFieldName + "=#{" + name.toString() + "} ");
							break;
						}
					}
				}
			}
			sql.append("order by " + obj.id() + " asc ");
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("queryByMap is error , reason is : " + e);
		}
		logger.debug("queryByMap--->" + sql.toString());
		return sql.toString();
	}

	public String getMaxKey(Class<? extends BizObject> clazz)
			throws TenbentException, InstantiationException, IllegalAccessException {

		BizObject obj = clazz.newInstance();
		StringBuffer sql = new StringBuffer();
		sql.append("select max(" + obj.id() + ") as id from " + obj.tablename());
		logger.debug("getMaxKey--->" + sql.toString());
		return sql.toString();
	}

}
